/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qandroidmultimediautils.h"

#include <qlist.h>

QT_BEGIN_NAMESPACE

int qt_findClosestValue(const QList<int> &list, int value)
{
    if (list.size() < 2)
        return 0;

    int begin = 0;
    int end = list.size() - 1;
    int pivot = begin + (end - begin) / 2;
    int v = list.at(pivot);

    while (end - begin > 1) {
        if (value == v)
            return pivot;

        if (value > v)
            begin = pivot;
        else
            end = pivot;

        pivot = begin + (end - begin) / 2;
        v = list.at(pivot);
    }

    return value - v >= list.at(pivot + 1) - value ? pivot + 1 : pivot;
}

bool qt_sizeLessThan(const QSize &s1, const QSize &s2)
{
    return s1.width() * s1.height() < s2.width() * s2.height();
}

// Pre-computed Y coefficients for all possible y values (0-255). Stored as fixed-point (16:16)
// Y = 1.164 * (y - 16)
static const int coefficientsY[256] = {
    -593888, -555746, -517604, -479462, -441320, -403178, -365036, -326894, -288752, -250610,
    -212468, -174326, -136184,  -98042,  -59900,  -21758,   16384,   54526,   92668,  130810,
     168952,  207094,  245236,  283378,  321520,  359662,  397804,  435946,  474088,  512230,
     550372,  588514,  626656,  664798,  702940,  741082,  779224,  817366,  855508,  893650,
     931792,  969934, 1008076, 1046218, 1084360, 1122502, 1160644, 1198786, 1236928, 1275070,
    1313212, 1351354, 1389496, 1427638, 1465780, 1503922, 1542064, 1580206, 1618348, 1656490,
    1694632, 1732774, 1770916, 1809058, 1847200, 1885342, 1923484, 1961626, 1999768, 2037910,
    2076052, 2114194, 2152336, 2190478, 2228620, 2266762, 2304904, 2343046, 2381188, 2419330,
    2457472, 2495614, 2533756, 2571898, 2610040, 2648182, 2686324, 2724466, 2762608, 2800750,
    2838892, 2877034, 2915176, 2953318, 2991460, 3029602, 3067744, 3105886, 3144028, 3182170,
    3220312, 3258454, 3296596, 3334738, 3372880, 3411022, 3449164, 3487306, 3525448, 3563590,
    3601732, 3639874, 3678016, 3716158, 3754300, 3792442, 3830584, 3868726, 3906868, 3945010,
    3983152, 4021294, 4059436, 4097578, 4135720, 4173862, 4212004, 4250146, 4288288, 4326430,
    4364572, 4402714, 4440856, 4478998, 4517140, 4555282, 4593424, 4631566, 4669708, 4707850,
    4745992, 4784134, 4822276, 4860418, 4898560, 4936702, 4974844, 5012986, 5051128, 5089270,
    5127412, 5165554, 5203696, 5241838, 5279980, 5318122, 5356264, 5394406, 5432548, 5470690,
    5508832, 5546974, 5585116, 5623258, 5661400, 5699542, 5737684, 5775826, 5813968, 5852110,
    5890252, 5928394, 5966536, 6004678, 6042820, 6080962, 6119104, 6157246, 6195388, 6233530,
    6271672, 6309814, 6347956, 6386098, 6424240, 6462382, 6500524, 6538666, 6576808, 6614950,
    6653092, 6691234, 6729376, 6767518, 6805660, 6843802, 6881944, 6920086, 6958228, 6996370,
    7034512, 7072654, 7110796, 7148938, 7187080, 7225222, 7263364, 7301506, 7339648, 7377790,
    7415932, 7454074, 7492216, 7530358, 7568500, 7606642, 7644784, 7682926, 7721068, 7759210,
    7797352, 7835494, 7873636, 7911778, 7949920, 7988062, 8026204, 8064346, 8102488, 8140630,
    8178772, 8216914, 8255056, 8293198, 8331340, 8369482, 8407624, 8445766, 8483908, 8522050,
    8560192, 8598334, 8636476, 8674618, 8712760, 8750902, 8789044, 8827186, 8865328, 8903470,
    8941612, 8979754, 9017896, 9056038, 9094180, 9132322
};

// V lookup table for the Red component. Stored as fixed-point (16:16).
// V = 1.596 * (v - 128)
static const int coefficientsRV[256] = {
    -6694144, -6641846, -6589548, -6537250, -6484952, -6432654, -6380356, -6328058, -6275760,
    -6223462, -6171164, -6118866, -6066568, -6014270, -5961972, -5909674, -5857376, -5805078,
    -5752780, -5700482, -5648184, -5595886, -5543588, -5491290, -5438992, -5386694, -5334396,
    -5282098, -5229800, -5177502, -5125204, -5072906, -5020608, -4968310, -4916012, -4863714,
    -4811416, -4759118, -4706820, -4654522, -4602224, -4549926, -4497628, -4445330, -4393032,
    -4340734, -4288436, -4236138, -4183840, -4131542, -4079244, -4026946, -3974648, -3922350,
    -3870052, -3817754, -3765456, -3713158, -3660860, -3608562, -3556264, -3503966, -3451668,
    -3399370, -3347072, -3294774, -3242476, -3190178, -3137880, -3085582, -3033284, -2980986,
    -2928688, -2876390, -2824092, -2771794, -2719496, -2667198, -2614900, -2562602, -2510304,
    -2458006, -2405708, -2353410, -2301112, -2248814, -2196516, -2144218, -2091920, -2039622,
    -1987324, -1935026, -1882728, -1830430, -1778132, -1725834, -1673536, -1621238, -1568940,
    -1516642, -1464344, -1412046, -1359748, -1307450, -1255152, -1202854, -1150556, -1098258,
    -1045960,  -993662,  -941364,  -889066,  -836768,  -784470,  -732172,  -679874,  -627576,
     -575278,  -522980,  -470682,  -418384,  -366086,  -313788,  -261490,  -209192,  -156894,
     -104596,   -52298,        0,    52298,   104596,   156894,   209192,   261490,   313788,
      366086,   418384,   470682,   522980,   575278,   627576,   679874,   732172,   784470,
      836768,   889066,   941364,   993662,  1045960,  1098258,  1150556,  1202854,  1255152,
     1307450,  1359748,  1412046,  1464344,  1516642,  1568940,  1621238,  1673536,  1725834,
     1778132,  1830430,  1882728,  1935026,  1987324,  2039622,  2091920,  2144218,  2196516,
     2248814,  2301112,  2353410,  2405708,  2458006,  2510304,  2562602,  2614900,  2667198,
     2719496,  2771794,  2824092,  2876390,  2928688,  2980986,  3033284,  3085582,  3137880,
     3190178,  3242476,  3294774,  3347072,  3399370,  3451668,  3503966,  3556264,  3608562,
     3660860,  3713158,  3765456,  3817754,  3870052,  3922350,  3974648,  4026946,  4079244,
     4131542,  4183840,  4236138,  4288436,  4340734,  4393032,  4445330,  4497628,  4549926,
     4602224,  4654522,  4706820,  4759118,  4811416,  4863714,  4916012,  4968310,  5020608,
     5072906,  5125204,  5177502,  5229800,  5282098,  5334396,  5386694,  5438992,  5491290,
     5543588,  5595886,  5648184,  5700482,  5752780,  5805078,  5857376,  5909674,  5961972,
     6014270,  6066568,  6118866,  6171164,  6223462,  6275760,  6328058,  6380356,  6432654,
     6484952,  6537250,  6589548,  6641846
};

// U lookup table for the Green component. Stored as fixed-point (16:16).
// U = 0.391 * (u - 128)
static const int coefficientsGU[256] = {
     1639936,  1627124,  1614312,  1601500,  1588688,  1575876,  1563064,  1550252,  1537440,
     1524628,  1511816,  1499004,  1486192,  1473380,  1460568,  1447756,  1434944,  1422132,
     1409320,  1396508,  1383696,  1370884,  1358072,  1345260,  1332448,  1319636,  1306824,
     1294012,  1281200,  1268388,  1255576,  1242764,  1229952,  1217140,  1204328,  1191516,
     1178704,  1165892,  1153080,  1140268,  1127456,  1114644,  1101832,  1089020,  1076208,
     1063396,  1050584,  1037772,  1024960,  1012148,   999336,   986524,   973712,   960900,
      948088,   935276,   922464,   909652,   896840,   884028,   871216,   858404,   845592,
      832780,   819968,   807156,   794344,   781532,   768720,   755908,   743096,   730284,
      717472,   704660,   691848,   679036,   666224,   653412,   640600,   627788,   614976,
      602164,   589352,   576540,   563728,   550916,   538104,   525292,   512480,   499668,
      486856,   474044,   461232,   448420,   435608,   422796,   409984,   397172,   384360,
      371548,   358736,   345924,   333112,   320300,   307488,   294676,   281864,   269052,
      256240,   243428,   230616,   217804,   204992,   192180,   179368,   166556,   153744,
      140932,   128120,   115308,   102496,    89684,    76872,    64060,    51248,    38436,
       25624,    12812,        0,   -12812,   -25624,   -38436,   -51248,   -64060,   -76872,
      -89684,  -102496,  -115308,  -128120,  -140932,  -153744,  -166556,  -179368,  -192180,
     -204992,  -217804,  -230616,  -243428,  -256240,  -269052,  -281864,  -294676,  -307488,
     -320300,  -333112,  -345924,  -358736,  -371548,  -384360,  -397172,  -409984,  -422796,
     -435608,  -448420,  -461232,  -474044,  -486856,  -499668,  -512480,  -525292,  -538104,
     -550916,  -563728,  -576540,  -589352,  -602164,  -614976,  -627788,  -640600,  -653412,
     -666224,  -679036,  -691848,  -704660,  -717472,  -730284,  -743096,  -755908,  -768720,
     -781532,  -794344,  -807156,  -819968,  -832780,  -845592,  -858404,  -871216,  -884028,
     -896840,  -909652,  -922464,  -935276,  -948088,  -960900,  -973712,  -986524,  -999336,
    -1012148, -1024960, -1037772, -1050584, -1063396, -1076208, -1089020, -1101832, -1114644,
    -1127456, -1140268, -1153080, -1165892, -1178704, -1191516, -1204328, -1217140, -1229952,
    -1242764, -1255576, -1268388, -1281200, -1294012, -1306824, -1319636, -1332448, -1345260,
    -1358072, -1370884, -1383696, -1396508, -1409320, -1422132, -1434944, -1447756, -1460568,
    -1473380, -1486192, -1499004, -1511816, -1524628, -1537440, -1550252, -1563064, -1575876,
    -1588688, -1601500, -1614312, -1627124
};

// V lookup table for the Green component. Stored as fixed-point (16:16).
// V = 0.813 * (v - 128)
static const int coefficientsGV[256] = {
     3409920,  3383280,  3356640,  3330000,  3303360,  3276720,  3250080,  3223440,  3196800,
     3170160,  3143520,  3116880,  3090240,  3063600,  3036960,  3010320,  2983680,  2957040,
     2930400,  2903760,  2877120,  2850480,  2823840,  2797200,  2770560,  2743920,  2717280,
     2690640,  2664000,  2637360,  2610720,  2584080,  2557440,  2530800,  2504160,  2477520,
     2450880,  2424240,  2397600,  2370960,  2344320,  2317680,  2291040,  2264400,  2237760,
     2211120,  2184480,  2157840,  2131200,  2104560,  2077920,  2051280,  2024640,  1998000,
     1971360,  1944720,  1918080,  1891440,  1864800,  1838160,  1811520,  1784880,  1758240,
     1731600,  1704960,  1678320,  1651680,  1625040,  1598400,  1571760,  1545120,  1518480,
     1491840,  1465200,  1438560,  1411920,  1385280,  1358640,  1332000,  1305360,  1278720,
     1252080,  1225440,  1198800,  1172160,  1145520,  1118880,  1092240,  1065600,  1038960,
     1012320,   985680,   959040,   932400,   905760,   879120,   852480,   825840,   799200,
      772560,   745920,   719280,   692640,   666000,   639360,   612720,   586080,   559440,
      532800,   506160,   479520,   452880,   426240,   399600,   372960,   346320,   319680,
      293040,   266400,   239760,   213120,   186480,   159840,   133200,   106560,    79920,
       53280,    26640,        0,   -26640,   -53280,   -79920,  -106560,  -133200,  -159840,
     -186480,  -213120,  -239760,  -266400,  -293040,  -319680,  -346320,  -372960,  -399600,
     -426240,  -452880,  -479520,  -506160,  -532800,  -559440,  -586080,  -612720,  -639360,
     -666000,  -692640,  -719280,  -745920,  -772560,  -799200,  -825840,  -852480,  -879120,
     -905760,  -932400,  -959040,  -985680, -1012320, -1038960, -1065600, -1092240, -1118880,
    -1145520, -1172160, -1198800, -1225440, -1252080, -1278720, -1305360, -1332000, -1358640,
    -1385280, -1411920, -1438560, -1465200, -1491840, -1518480, -1545120, -1571760, -1598400,
    -1625040, -1651680, -1678320, -1704960, -1731600, -1758240, -1784880, -1811520, -1838160,
    -1864800, -1891440, -1918080, -1944720, -1971360, -1998000, -2024640, -2051280, -2077920,
    -2104560, -2131200, -2157840, -2184480, -2211120, -2237760, -2264400, -2291040, -2317680,
    -2344320, -2370960, -2397600, -2424240, -2450880, -2477520, -2504160, -2530800, -2557440,
    -2584080, -2610720, -2637360, -2664000, -2690640, -2717280, -2743920, -2770560, -2797200,
    -2823840, -2850480, -2877120, -2903760, -2930400, -2957040, -2983680, -3010320, -3036960,
    -3063600, -3090240, -3116880, -3143520, -3170160, -3196800, -3223440, -3250080, -3276720,
    -3303360, -3330000, -3356640, -3383280
};

// U lookup table for the Blue component. Stored as fixed-point (16:16).
// U = 2.018 * (u - 128)
static const int coefficientsBU[256] = {
    -8464128, -8398002, -8331876, -8265750, -8199624, -8133498, -8067372, -8001246, -7935120,
    -7868994, -7802868, -7736742, -7670616, -7604490, -7538364, -7472238, -7406112, -7339986,
    -7273860, -7207734, -7141608, -7075482, -7009356, -6943230, -6877104, -6810978, -6744852,
    -6678726, -6612600, -6546474, -6480348, -6414222, -6348096, -6281970, -6215844, -6149718,
    -6083592, -6017466, -5951340, -5885214, -5819088, -5752962, -5686836, -5620710, -5554584,
    -5488458, -5422332, -5356206, -5290080, -5223954, -5157828, -5091702, -5025576, -4959450,
    -4893324, -4827198, -4761072, -4694946, -4628820, -4562694, -4496568, -4430442, -4364316,
    -4298190, -4232064, -4165938, -4099812, -4033686, -3967560, -3901434, -3835308, -3769182,
    -3703056, -3636930, -3570804, -3504678, -3438552, -3372426, -3306300, -3240174, -3174048,
    -3107922, -3041796, -2975670, -2909544, -2843418, -2777292, -2711166, -2645040, -2578914,
    -2512788, -2446662, -2380536, -2314410, -2248284, -2182158, -2116032, -2049906, -1983780,
    -1917654, -1851528, -1785402, -1719276, -1653150, -1587024, -1520898, -1454772, -1388646,
    -1322520, -1256394, -1190268, -1124142, -1058016,  -991890,  -925764,  -859638,  -793512,
     -727386,  -661260,  -595134,  -529008,  -462882,  -396756,  -330630,  -264504,  -198378,
     -132252,   -66126,        0,    66126,   132252,   198378,   264504,   330630,   396756,
      462882,   529008,   595134,   661260,   727386,   793512,   859638,   925764,   991890,
     1058016,  1124142,  1190268,  1256394,  1322520,  1388646,  1454772,  1520898,  1587024,
     1653150,  1719276,  1785402,  1851528,  1917654,  1983780,  2049906,  2116032,  2182158,
     2248284,  2314410,  2380536,  2446662,  2512788,  2578914,  2645040,  2711166,  2777292,
     2843418,  2909544,  2975670,  3041796,  3107922,  3174048,  3240174,  3306300,  3372426,
     3438552,  3504678,  3570804,  3636930,  3703056,  3769182,  3835308,  3901434,  3967560,
     4033686,  4099812,  4165938,  4232064,  4298190,  4364316,  4430442,  4496568,  4562694,
     4628820,  4694946,  4761072,  4827198,  4893324,  4959450,  5025576,  5091702,  5157828,
     5223954,  5290080,  5356206,  5422332,  5488458,  5554584,  5620710,  5686836,  5752962,
     5819088,  5885214,  5951340,  6017466,  6083592,  6149718,  6215844,  6281970,  6348096,
     6414222,  6480348,  6546474,  6612600,  6678726,  6744852,  6810978,  6877104,  6943230,
     7009356,  7075482,  7141608,  7207734,  7273860,  7339986,  7406112,  7472238,  7538364,
     7604490,  7670616,  7736742,  7802868,  7868994,  7935120,  8001246,  8067372,  8133498,
     8199624,  8265750,  8331876,  8398002
};

// R = min(max(r, 0), 255) << 16
// where 'r' is the converted red component from YUV, which is always in the range -320 <= r < 704
// and needs to be clamped to 0-255. It also precomputes the bitshift needed to create an RGB value.
static const quint32 _clampedR[1024] = {
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,        0,        0,        0,        0,        0,        0,        0,
           0,    65536,   131072,   196608,   262144,   327680,   393216,   458752,
      524288,   589824,   655360,   720896,   786432,   851968,   917504,   983040,
     1048576,  1114112,  1179648,  1245184,  1310720,  1376256,  1441792,  1507328,
     1572864,  1638400,  1703936,  1769472,  1835008,  1900544,  1966080,  2031616,
     2097152,  2162688,  2228224,  2293760,  2359296,  2424832,  2490368,  2555904,
     2621440,  2686976,  2752512,  2818048,  2883584,  2949120,  3014656,  3080192,
     3145728,  3211264,  3276800,  3342336,  3407872,  3473408,  3538944,  3604480,
     3670016,  3735552,  3801088,  3866624,  3932160,  3997696,  4063232,  4128768,
     4194304,  4259840,  4325376,  4390912,  4456448,  4521984,  4587520,  4653056,
     4718592,  4784128,  4849664,  4915200,  4980736,  5046272,  5111808,  5177344,
     5242880,  5308416,  5373952,  5439488,  5505024,  5570560,  5636096,  5701632,
     5767168,  5832704,  5898240,  5963776,  6029312,  6094848,  6160384,  6225920,
     6291456,  6356992,  6422528,  6488064,  6553600,  6619136,  6684672,  6750208,
     6815744,  6881280,  6946816,  7012352,  7077888,  7143424,  7208960,  7274496,
     7340032,  7405568,  7471104,  7536640,  7602176,  7667712,  7733248,  7798784,
     7864320,  7929856,  7995392,  8060928,  8126464,  8192000,  8257536,  8323072,
     8388608,  8454144,  8519680,  8585216,  8650752,  8716288,  8781824,  8847360,
     8912896,  8978432,  9043968,  9109504,  9175040,  9240576,  9306112,  9371648,
     9437184,  9502720,  9568256,  9633792,  9699328,  9764864,  9830400,  9895936,
     9961472, 10027008, 10092544, 10158080, 10223616, 10289152, 10354688, 10420224,
    10485760, 10551296, 10616832, 10682368, 10747904, 10813440, 10878976, 10944512,
    11010048, 11075584, 11141120, 11206656, 11272192, 11337728, 11403264, 11468800,
    11534336, 11599872, 11665408, 11730944, 11796480, 11862016, 11927552, 11993088,
    12058624, 12124160, 12189696, 12255232, 12320768, 12386304, 12451840, 12517376,
    12582912, 12648448, 12713984, 12779520, 12845056, 12910592, 12976128, 13041664,
    13107200, 13172736, 13238272, 13303808, 13369344, 13434880, 13500416, 13565952,
    13631488, 13697024, 13762560, 13828096, 13893632, 13959168, 14024704, 14090240,
    14155776, 14221312, 14286848, 14352384, 14417920, 14483456, 14548992, 14614528,
    14680064, 14745600, 14811136, 14876672, 14942208, 15007744, 15073280, 15138816,
    15204352, 15269888, 15335424, 15400960, 15466496, 15532032, 15597568, 15663104,
    15728640, 15794176, 15859712, 15925248, 15990784, 16056320, 16121856, 16187392,
    16252928, 16318464, 16384000, 16449536, 16515072, 16580608, 16646144, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680,
    16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680, 16711680
};

// G = min(max(g, 0), 255) << 8
// where 'g' is the converted green component from YUV, which is always in the range -320 <= r < 704
// and needs to be clamped to 0-255. It also precomputes the bitshift needed to create an RGB value.
static const quint32 _clampedG[1024] = {
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,
        0,   256,   512,   768,  1024,  1280,  1536,  1792,
     2048,  2304,  2560,  2816,  3072,  3328,  3584,  3840,
     4096,  4352,  4608,  4864,  5120,  5376,  5632,  5888,
     6144,  6400,  6656,  6912,  7168,  7424,  7680,  7936,
     8192,  8448,  8704,  8960,  9216,  9472,  9728,  9984,
    10240, 10496, 10752, 11008, 11264, 11520, 11776, 12032,
    12288, 12544, 12800, 13056, 13312, 13568, 13824, 14080,
    14336, 14592, 14848, 15104, 15360, 15616, 15872, 16128,
    16384, 16640, 16896, 17152, 17408, 17664, 17920, 18176,
    18432, 18688, 18944, 19200, 19456, 19712, 19968, 20224,
    20480, 20736, 20992, 21248, 21504, 21760, 22016, 22272,
    22528, 22784, 23040, 23296, 23552, 23808, 24064, 24320,
    24576, 24832, 25088, 25344, 25600, 25856, 26112, 26368,
    26624, 26880, 27136, 27392, 27648, 27904, 28160, 28416,
    28672, 28928, 29184, 29440, 29696, 29952, 30208, 30464,
    30720, 30976, 31232, 31488, 31744, 32000, 32256, 32512,
    32768, 33024, 33280, 33536, 33792, 34048, 34304, 34560,
    34816, 35072, 35328, 35584, 35840, 36096, 36352, 36608,
    36864, 37120, 37376, 37632, 37888, 38144, 38400, 38656,
    38912, 39168, 39424, 39680, 39936, 40192, 40448, 40704,
    40960, 41216, 41472, 41728, 41984, 42240, 42496, 42752,
    43008, 43264, 43520, 43776, 44032, 44288, 44544, 44800,
    45056, 45312, 45568, 45824, 46080, 46336, 46592, 46848,
    47104, 47360, 47616, 47872, 48128, 48384, 48640, 48896,
    49152, 49408, 49664, 49920, 50176, 50432, 50688, 50944,
    51200, 51456, 51712, 51968, 52224, 52480, 52736, 52992,
    53248, 53504, 53760, 54016, 54272, 54528, 54784, 55040,
    55296, 55552, 55808, 56064, 56320, 56576, 56832, 57088,
    57344, 57600, 57856, 58112, 58368, 58624, 58880, 59136,
    59392, 59648, 59904, 60160, 60416, 60672, 60928, 61184,
    61440, 61696, 61952, 62208, 62464, 62720, 62976, 63232,
    63488, 63744, 64000, 64256, 64512, 64768, 65024, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280,
    65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280
};

// B = min(max(b, 0), 255)
// where 'b' is the converted blue component from YUV, which is always in the range -320 <= r < 704
static const quint32 _clampedB[1024] = {
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
     16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
     32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
     48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
     64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
     80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
     96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
    112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
    128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
    144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
    160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
    176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
    192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
    208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
    224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
    240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
};

static const quint32 *clampedR = _clampedR + 320;
static const quint32 *clampedG = _clampedG + 320;
static const quint32 *clampedB = _clampedB + 320;

#define MAKE_RGB(r, g, b) 0xff000000 | clampedR[r] | clampedG[g] | clampedB[b]

void qt_convert_NV21_to_ARGB32(const uchar *yuv, quint32 *rgb, int width, int height)
{
    const uchar *y0 = yuv;
    const uchar *y1 = yuv + width;
    const uchar *vu = yuv + width * height;

    quint32 *rgb0 = rgb;
    quint32 *rgb1 = rgb + width;

    for (int i = 0; i < height; i += 2) {
        for (int j = 0; j < width; j += 2) {
            int v = *vu++;
            int u = *vu++;

            int ruv = coefficientsRV[v] >> 15;
            int guv = (coefficientsGU[u] + coefficientsGV[v]) >> 15;
            int buv = coefficientsBU[u] >> 15;

            int y = coefficientsY[*y0++] >> 15;
            int r = y + ruv;
            int g = y + guv;
            int b = y + buv;
            *rgb0++ = MAKE_RGB(r, g, b);

            y = coefficientsY[*y0++] >> 15;
            r = y + ruv;
            g = y + guv;
            b = y + buv;
            *rgb0++ = MAKE_RGB(r, g, b);

            y = coefficientsY[*y1++] >> 15;
            r = y + ruv;
            g = y + guv;
            b = y + buv;
            *rgb1++ = MAKE_RGB(r, g, b);

            y = coefficientsY[*y1++] >> 15;
            r = y + ruv;
            g = y + guv;
            b = y + buv;
            *rgb1++ = MAKE_RGB(r, g, b);
        }

        rgb0 += width;
        rgb1 += width;
        y0 += width;
        y1 += width;
    }
}

QT_END_NAMESPACE
